package com.punai.customer.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.github.pagehelper.PageInfo;
import com.punai.common.core.domain.TreeBo;
import com.punai.common.core.page.TableDataInfo;
import com.punai.common.exception.ServiceException;
import com.punai.common.utils.PageUtils;
import com.punai.common.utils.ParseContentUtil;
import com.punai.common.utils.SecurityUtils;
import com.punai.common.utils.StringUtils;
import com.punai.customer.domain.CusFbFee;
import com.punai.customer.domain.CusGxChapter;
import com.punai.customer.domain.CusGxFee;
import com.punai.customer.domain.CusLinkFbGx;
import com.punai.customer.domain.bo.*;
import com.punai.customer.domain.contants.CusConstants;
import com.punai.customer.domain.vo.AddSupLinkFbGxVo;
import com.punai.customer.domain.vo.CusFbVo;
import com.punai.customer.mapper.*;
import com.punai.customer.service.IFBSupportService;
import com.punai.standard.domain.StaGxChapter;
import com.punai.standard.domain.StaGxFee;
import com.punai.standard.domain.StaVersion;
import com.punai.standard.domain.constants.StaConstants;
import com.punai.standard.domain.vo.StaFeeVo;
import com.punai.standard.mapper.StaGxChapterMapper;
import com.punai.standard.mapper.StaGxFeeMapper;
import com.punai.standard.mapper.StaVersionMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

@Service
public class FBSupportServiceImpl implements IFBSupportService {

    @Autowired
    private CusGxChapterMapper cusGxChapterMapper;
    @Autowired
    private CusLinkFbGxMapper cusLinkFbGxMapper;
    @Autowired
    private CusGxFeeMapper cusGxFeeMapper;
    @Autowired
    private CusLinkFbFeatureMapper cusLinkFbFeatureMapper;
    @Autowired
    private CusExpenseCategoriesMapper cusExpenseCategoriesMapper;
    @Autowired
    private StaGxChapterMapper staGxChapterMapper;
    @Autowired
    private StaGxFeeMapper staGxFeeMapper;
    @Autowired
    private StaVersionMapper staVersionMapper;
    @Autowired
    private CusFbFeeMapper cusFbFeeMapper;
    @Autowired
    private CusVersionsDiscrepancyMapper cusVersionsDiscrepancyMapper;

    @Override
    public TableDataInfo getGxList(CusFbVo vo) {
        Long companyId = SecurityUtils.getCompanyId();
        String topId = vo.getTopId();
        String gxChapterId = vo.getChapterId();
        String subcontractId = vo.getSubcontractId();
        List<CusGxChapter> gxChapters = cusGxChapterMapper.selectChildrenById(gxChapterId, companyId);
        List<String> chapterIds = gxChapters.stream().map(CusGxChapter::getId).collect(Collectors.toList());
        chapterIds.add(gxChapterId);

        LambdaQueryWrapper<CusGxFee> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(CusGxFee::getCompanyId, companyId)
                .eq(CusGxFee::getSpecId, topId)
                .in(CusGxFee::getChapterId, chapterIds);

        if (StringUtils.isEmpty(subcontractId)) {

            LambdaQueryWrapper<CusLinkFbGx> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(CusLinkFbGx::getSort,"1");
            queryWrapper.eq(CusLinkFbGx::getCompanyId, companyId);

            List<CusLinkFbGx> cusLinkFbGxList = cusLinkFbGxMapper.selectList(queryWrapper);
            List<String> cusLinkFbGxIds = cusLinkFbGxList.stream().map(CusLinkFbGx::getId).collect(Collectors.toList());

            if(cusLinkFbGxIds.size() > 0) {
                wrapper.notIn(CusGxFee::getId, cusLinkFbGxIds);
            }
        }else {
            List<CusLinkFbGx> cusLinkFbGxes = cusLinkFbGxMapper.selectList(Wrappers.<CusLinkFbGx>lambdaQuery()
                    .eq(CusLinkFbGx::getFbId, subcontractId)
                    .eq(CusLinkFbGx::getCompanyId,companyId)
            );
            List<String> CusLinkFbGxIds = cusLinkFbGxes.stream().map(CusLinkFbGx::getGxId).collect(Collectors.toList());

            wrapper.notIn(CusGxFee::getId,CusLinkFbGxIds);
        }
        PageUtils.startPage();

        List<CusGxFee> cusGxFees = cusGxFeeMapper.selectList(wrapper);

        for (CusGxFee cusGxFee : cusGxFees) {
            // 调整工作内容展示
            String content = cusGxFee.getContent();
            content = ParseContentUtil.parseContent(content);
            cusGxFee.setContent(content);
        }
        Long total = new PageInfo(cusGxFees).getTotal();
        return new TableDataInfo(cusGxFees, total.intValue());
    }

    @Override
    @Transactional
    public Integer insertSupLinkFbGx(AddSupLinkFbGxVo vo) {
        String fbId = vo.getFbId();
        List<String> gxIds = vo.getGxIds();
        if (CollUtil.isNotEmpty(gxIds)) {
            Integer sort = cusLinkFbGxMapper.getMaxSort(fbId, SecurityUtils.getCompanyId());
            List<CusLinkFbGx> cusLinkFbGxList = new ArrayList<>();
            for (String gxId : gxIds) {
                CusLinkFbGx linkFbGx = new CusLinkFbGx();
                linkFbGx.setFbId(fbId);
                linkFbGx.setCompanyId(SecurityUtils.getCompanyId());
                linkFbGx.setGxId(gxId);
                linkFbGx.setEnable("Y");
                linkFbGx.setSort(++sort);
                cusLinkFbGxList.add(linkFbGx);
            }
            cusLinkFbGxMapper.insertBatchSomeColumn(cusLinkFbGxList);
        }
        return 1;
    }

    @Override
    public ChangeGxListBo changeGxList(String versionId,String fbId,String gxIds, Long companyId) {
        ChangeGxListBo res = new ChangeGxListBo();
        // 获取工作内容
        if (StrUtil.isEmpty(gxIds)) {
            return res;
        }
        CusFbFee cusFbFee = cusFbFeeMapper.selectOne(Wrappers.<CusFbFee>lambdaQuery()
                .eq(CusFbFee::getCompanyId, companyId)
                .eq(CusFbFee::getId, fbId));

        // 拿到的工序id
        List<String> gxIdList = StrUtil.split(gxIds, ",");
        List<StaGxFee> gxFees = staGxFeeMapper.selectList(
                Wrappers.<StaGxFee>lambdaQuery()
                        .eq(StaGxFee::getVersionId, versionId)
                        .in(StaGxFee::getId, gxIdList)
        );

        Map<String, StaGxFee> gxMap = gxFees.stream().collect(Collectors.toMap(StaGxFee::getId, Function.identity()));

        // 拿到关联的工序id
        List<CusLinkFbGx> linkFbGxes = cusLinkFbGxMapper.selectList(Wrappers.<CusLinkFbGx>lambdaQuery()
                .eq(CusLinkFbGx::getCompanyId, companyId)
                .eq(CusLinkFbGx::getFbId, fbId)
                .in(CusLinkFbGx::getGxId,gxIdList)
                .orderByAsc(CusLinkFbGx::getSort)
        );

        Map<String, List<String>> fbContent = ParseContentUtil.getContentObj();
        List<String> subRange = new ArrayList<>();
        List<GxFeeBo> gxFeeList = new ArrayList<>();
        for (CusLinkFbGx linkFbGx : linkFbGxes) {
            GxFeeBo gxFeeBo = new GxFeeBo();
            StaGxFee gxFee = gxMap.get(linkFbGx.getGxId());
            gxFeeBo.setId(gxFee.getId());
            gxFeeBo.setName(gxFee.getName());
            gxFeeBo.setUnit(gxFee.getUnit());
            gxFeeBo.setSuitableRange(gxFee.getSuitableRange());

            subRange.add(gxFee.getSuitableRange());
            gxFeeBo.setLinkId(linkFbGx.getId());
            gxFeeBo.setEnable(linkFbGx.getEnable());
            gxFeeBo.setOrderNum(linkFbGx.getSort());
            gxFeeList.add(gxFeeBo);
            Map<String, List<String>> parseBo = ParseContentUtil.parseObject(gxFee.getContent());
            if (parseBo.get("gygx") != null) {
                fbContent.get("gygx").addAll(parseBo.get("gygx"));
            }
            if (parseBo.get("qtnr") != null) {
                fbContent.get("qtnr").addAll(parseBo.get("qtnr"));
            }
            if (parseBo.get("bcnr") != null) {
                fbContent.get("bcnr").addAll(parseBo.get("bcnr"));
            }
        }
        //补充工作内容
        Map<String, List<String>> parseBo = ParseContentUtil.parseObject(cusFbFee.getContent());
        if (parseBo.get("bcnr") != null) {
            fbContent.get("bcnr").addAll(parseBo.get("bcnr"));
        }
        res.setContentJoint(ParseContentUtil.parseContent(fbContent));
        res.setSuitableRangeJoint(StrUtil.join("；", subRange) + "；");

        // 获取特征
        List<CusFeatureBo> cusFeatureBos = cusLinkFbFeatureMapper.selectLinkFeature(companyId,gxIdList,CusConstants.GX_TYPE);

        ArrayList<CusFeatureBo> cusFeatureBoList = cusFeatureBos.stream().collect(Collectors.collectingAndThen(
                Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(CusFeatureBo::getId))), ArrayList::new));

        List<FeatureRes> featureResList = new ArrayList<>();
        if (CollUtil.isNotEmpty(cusFeatureBoList)) {
            for (CusFeatureBo cusFeatureBo : cusFeatureBoList) {
                FeatureRes featureRes = new FeatureRes();
                featureRes.setLinkId(cusFeatureBo.getLinkId());
                featureRes.setFeatureId(cusFeatureBo.getId());
                featureRes.setFeatureName(cusFeatureBo.getFeatureName());
                String featureValues = cusFeatureBo.getFeatureValues();
                if (StrUtil.isNotEmpty(featureValues)) {
                    featureValues.replaceAll("|","，");
                }
                featureRes.setInputEntry(cusFeatureBo.getIsInput());
                featureRes.setDefValue(featureValues);
                featureResList.add(featureRes);
            }
        }
        res.setFeatureResList(featureResList);

        // 查询材机类别
        List<CusCategoryBo> cusCategoryBos = cusExpenseCategoriesMapper.selectGxFbLinkDataAndEntitySta(companyId,versionId,gxIdList);

        ArrayList<CusCategoryBo> cusCategoryBoList = cusCategoryBos.stream().collect(Collectors.collectingAndThen(
                Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(CusCategoryBo::getId))), ArrayList::new));

        if (CollUtil.isNotEmpty(cusCategoryBoList)) {
            List<CJFlRes> cjFlRes = new ArrayList<>();
            gxMap.forEach((k,v) -> {
                List<CusCategoryBo> collect = cusCategoryBoList.stream().filter(e -> k.equals(e.getSubpkId())).collect(Collectors.toList());
                if (CollUtil.isNotEmpty(collect)) {
                    for (CusCategoryBo cusCategoryBo : collect) {
                        CJFlRes cjFlResNew = new CJFlRes();
                        cjFlResNew.setName(v.getName() + "-" + cusCategoryBo.getCategoriesName());
                        cjFlResNew.setSpec(cusCategoryBo.getSpec());
                        cjFlResNew.setUnit(cusCategoryBo.getUnit());
                        cjFlResNew.setType(cusCategoryBo.getType());
                        cjFlRes.add(cjFlResNew);
                    }
                }
            });
            res.setCjflList(cjFlRes);
        }
        return res;
    }

    @Override
    public List<TreeBo> treeDataByTopId(String topId, Long companyId) {
        LambdaQueryWrapper<StaVersion> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(StaVersion::getCompanyId,companyId);
        wrapper.eq(StaVersion::getType, StaConstants.GX_TYPE);
        wrapper.eq(StaVersion::getSpecId,topId);
        wrapper.orderByDesc(StaVersion::getCreateTime);
        wrapper.last("limit 1");
        StaVersion staVersion = staVersionMapper.selectOne(wrapper);
        if(staVersion == null){
            throw new ServiceException("该版本未发布标准费用项");
        }

        List<StaGxChapter> staGxChapters = staGxChapterMapper.selectList(
                Wrappers.<StaGxChapter>lambdaQuery()
                        .eq(StaGxChapter::getVersionId, staVersion.getId())
        );

        List<TreeBo> result = new ArrayList<>();
        if (CollUtil.isEmpty(staGxChapters)) {
            return result;
        }
        result = TreeBo.convert(staGxChapters);
        return result.get(0).getChildren();
    }

    @Override
    public TableDataInfo getFeeListOnFb(StaFeeVo vo, Long companyId) {
        String chapterId = vo.getChapterId();
        String versionId = vo.getVersionId();
        String subcontractId = vo.getSubcontractId();
        List<String> chapterIds = new ArrayList<>();
        if (StrUtil.isNotEmpty(chapterId)) {
            chapterIds.add(chapterId);
            List<StaGxChapter> childByPid =  staGxChapterMapper.getChildByPid(chapterId,versionId);
            if (CollUtil.isNotEmpty(chapterIds)) {
                chapterIds.addAll(childByPid.stream().map(StaGxChapter::getId).collect(Collectors.toList()));
            }
        }

        LambdaQueryWrapper<StaGxFee> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(StaGxFee::getVersionId, versionId)
                .in(StaGxFee::getChapterId, chapterIds);
        if (StringUtils.isEmpty(subcontractId)) {

            LambdaQueryWrapper<CusLinkFbGx> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(CusLinkFbGx::getSort,"1");
            queryWrapper.eq(CusLinkFbGx::getCompanyId, companyId);

            List<CusLinkFbGx> cusLinkFbGxList = cusLinkFbGxMapper.selectList(queryWrapper);
            List<String> cusLinkFbGxIds = cusLinkFbGxList.stream().map(CusLinkFbGx::getGxId).collect(Collectors.toList());

            if(cusLinkFbGxIds.size() > 0) {
                wrapper.notIn(StaGxFee::getId, cusLinkFbGxIds);
            }
        }else {
            List<CusLinkFbGx> cusLinkFbGxes = cusLinkFbGxMapper.selectList(Wrappers.<CusLinkFbGx>lambdaQuery()
                    .eq(CusLinkFbGx::getFbId, subcontractId)
                    .eq(CusLinkFbGx::getCompanyId,companyId)
            );
            List<String> CusLinkFbGxIds = cusLinkFbGxes.stream().map(CusLinkFbGx::getGxId).collect(Collectors.toList());

            wrapper.notIn(StaGxFee::getId,CusLinkFbGxIds);
        }
        PageUtils.startPage();

        List<StaGxFee> staGxFees = staGxFeeMapper.selectList(wrapper);

        for (StaGxFee staGxFee : staGxFees) {
            String content = staGxFee.getContent();
            content = ParseContentUtil.parseContent(content);
            staGxFee.setContent(content);
        }
        Long total = new PageInfo(staGxFees).getTotal();
        return new TableDataInfo(staGxFees, total.intValue());

    }
}
